<template>
	<picker mode="multiSelector" :range="addressRange" range-key="name" @change="pickerChange"
		@columnchange="columnchange" :value="pickerValue" @cancel="$emit('cancel')" :disabled="disabled">
		<slot v-if="$slots.default"></slot>
		<input v-else type="text" :value="inputStr" disabled placeholder="请选择">
	</picker>
</template>

<script>
	import address from "../../utils/address.json"; // 可注释 注释此行请删除utils目录下的address.json文件
	export default {
		/**
		 * @param modelValue Array(string) ['四川省', '成都市', '武侯区']
		 * @param codeValue Array(string | number) [ "51","5101", "510107" ]
		 * @param selectIndex Array(number) [ 0, 0, 0 ]
		 * @param disabled 禁用
		 * @param loadJson 自定义加载地址json
		 */
		props: {
			modelValue: Array,
			value: Array,
			codeValue: Array,
			disabled: {
				type: Boolean,
				default: false,
			},
			selectIndex: {
				type: Array,
				default: () => [0, 0, 0],
			},
			loadJson: {
				type: Function,
			}
		},
		model: {
			prop: 'value',
			event: 'input'
		},
		emits: [
			"update:modelValue",
			"update:codeValue",
			"columnchange",
			"change",
			"cancel",
			"input",
		],
		computed: {
			inputStr() {
				if (this._value && this._value.length !== 0) {
					return Array.from(new Set(this._value || [])).join('');
				}
				if (this.value && this.value.length !== 0) {
					return Array.from(new Set(this.value || [])).join('');
				}
			},
			_value() {
				return this.value || this.modelValue;
			}
		},
		data() {
			return {
				addressRange: [],
				pickerValue: [0, 0, 0],
			};
		},
		async created() {
			this.pickerValue = [...this.selectIndex];
			if (this.loadJson) {
				const addressJson = await this.loadJson();
				if (!Array.isArray(addressJson)) {
					throw new Error('loadJson 必须返回数组');
				}
				this.addressRange[0] = addressJson
				console.warn('<sh-address> 您已自定义地址json, 请删除插件源码中指定可删除代码, 以减小应用体积');
			} else {
				this.addressRange[0] = address; // 可注释
			}
			this.setDefByCode();
			this.setDefByName();
		},
		watch: {
			_value() {
				this.setDefByName();
			},
			codeValue() {
				this.setDefByCode();
			},
		},
		methods: {
			columnchange(e) {
				const {
					column,
					value
				} = e.detail;
				this.$emit("columnchange", e.detail);
				if (column === 0) {
					this.addressRange[1] = this.addressRange[0][value].child;
					this.addressRange[2] = this.addressRange[1]?.[this.pickerValue[1]]?.child || this.addressRange[1][0]
						.child || [];
				}
				if (column === 1) {
					this.addressRange[2] = this.addressRange[1][value].child;
				}
				this.$forceUpdate()
			},
			pickerChange(e) {
				const v = e.detail.value;
				const {
					name: province,
					code: provinceCode
				} = this.addressRange[0][v[0]];
				const {
					name: city,
					code: cityCode
				} = this.addressRange[1][v[1]];
				const {
					code: areaCode,
					name: area,
				} = this.addressRange[2][v[2]];
				this.$emit("change", {
					areaCode,
					area,
					cityCode,
					provinceCode,
					province,
					city,
				});
				this.$emit("input", Array.from(new Set([province, city, area])));
				this.$emit("update:modelValue", Array.from(new Set([province, city, area])));
				this.$emit("update:codeValue", Array.from(new Set([provinceCode, cityCode, areaCode])));
			},
			setDefByCode() {
				if (this.codeValue instanceof Array && this.codeValue.length >= 1) {
					const provinceIndex = this.addressRange[0].findIndex(
						(item) => item.code === this.codeValue[0].toString()
					);
					if (provinceIndex === -1) {
						this.addressRange[1] = this.addressRange[0][0].child;
						this.addressRange[2] = this.addressRange[1][0].child;
						return;
					}
					this.addressRange[1] = this.addressRange[0][provinceIndex].child;

					const cityIndex = this.addressRange[1].findIndex(
						(item) => item.code === this.codeValue[1]?.toString()
					);
					if (cityIndex === -1) {
						this.addressRange[2] = this.addressRange[1][0].child;
						this.$nextTick(() => {
							this.pickerValue = [provinceIndex, 0, 0];
						});
						return;
					}
					this.addressRange[2] = this.addressRange[1][cityIndex].child;

					const areaIndex = this.addressRange[2].findIndex(
						(item) => item.code === this.codeValue[2]?.toString()
					);
					if (areaIndex === -1) {
						this.$nextTick(() => {
							this.pickerValue = [provinceIndex, cityIndex, 0];
						});
						return;
					}
					this.$nextTick(() => {
						this.pickerValue = [provinceIndex, cityIndex, areaIndex];
					});
				} else {
					this.addressRange[1] = this.addressRange[0][0].child;
					this.addressRange[2] = this.addressRange[1][0].child;
				}
			},
			setDefByName() {
				if (this._value instanceof Array && this._value.length >= 1) {
					const provinceIndex = this.addressRange[0].findIndex(
						(item) => item.name === this._value[0]
					);
					if (provinceIndex === -1) {
						this.addressRange[1] = this.addressRange[0][0].child;
						this.addressRange[2] = this.addressRange[1][0].child;
						return;
					}
					this.addressRange[1] = this.addressRange[0][provinceIndex].child;

					const cityIndex = this.addressRange[1].findIndex(
						(item) => item.name === this._value[1]
					);
					if (cityIndex === -1) {
						this.addressRange[2] = this.addressRange[1][0].child;
						this.$nextTick(() => {
							this.pickerValue = [provinceIndex, 0, 0];
						});
						return;
					}
					this.addressRange[2] = this.addressRange[1][cityIndex].child;

					const areaIndex = this.addressRange[2].findIndex(
						(item) => item.name === this._value[2]
					);
					if (areaIndex === -1) {
						this.$nextTick(() => {
							this.pickerValue = [provinceIndex, cityIndex, 0];
						});
						return;
					}
					this.$nextTick(() => {
						this.pickerValue = [provinceIndex, cityIndex, areaIndex];
					});
				} else {
					this.addressRange[1] = this.addressRange[0][0].child;
					this.addressRange[2] = this.addressRange[1][0].child;
				}
			},
		},
	};
</script>